//
//  STimeUtil.swift
//  niuguwang
//
//  Created by BrightLi on 2021/2/13.
//  Copyright © 2021年 taojinzhe. All rights reserved.
//


public typealias ChangeBlock = () -> ()
public typealias VoidBlock = @convention(block) ()->Void
public typealias STask = (_ cancel: Bool) -> Void
public typealias TimeBlock = (Int)->Void

import Foundation

@objcMembers public class STimeUtil:NSObject
{
    // GCD 信号锁
    static private let _lock = NSRecursiveLock()
    static var timeList:Dictionary<String,Date> = [:]
    static var timerList:Dictionary<String,DispatchSourceTimer> = [:]
    
    // 是否已启动计时器
    dynamic public class func hasTimer(_ key:String)->Bool
    {
        if key.isEmpty{
            return false
        }
        if let _ = timerList[key]{
            return true
        }
        return false
    }
    // 启动计时器
    dynamic public class func startTimer(_ key:String,millisecond:Int,take:Int,action:@escaping ChangeBlock)
    {
        if key.isEmpty{
            return
        }
        if let _ = timerList[key]{
            stopTimer(key)
        }
        let timer=DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
        timerList[key]=timer
        timer.schedule(deadline:DispatchTime.now(), repeating: .milliseconds(500))
        var time = 0
        timer.setEventHandler {
            time += 1
            if time >= take{
                STimeUtil.stopTimer(key)
                return
            }
            DispatchQueue.main.sync {
                action()
            }
        }
        timer.resume()
        SLog.debug("# STimeUtil 启动计时器:%@",key)
    }
    // 启动计时器
    dynamic public class func startTimer(_ key:String,second:Int,action:@escaping ChangeBlock)
    {
        if key.isEmpty{
            SLog.debug("# STimeUtil key不能为空")
            return
        }
        if let _ = timerList[key]{
            stopTimer(key)
        }
        let timer=DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
        timerList[key]=timer
        timer.schedule(deadline:DispatchTime.now(), repeating: .seconds(second))
        timer.setEventHandler {
            DispatchQueue.main.sync {
                action()
            }
        }
        timer.resume()
        SLog.debug("# STimeUtil 启动计时器:%@",key)
    }
    
    dynamic public class func startTimer(_ key:String,millisecond:Int,action:@escaping ChangeBlock)
    {
        if key.isEmpty{
            SLog.debug("# STimeUtil key不能为空")
            return
        }
        if let _ = timerList[key]{
            stopTimer(key)
        }
        let timer=DispatchSource.makeTimerSource(flags: [], queue: DispatchQueue.global())
        timerList[key]=timer
        timer.schedule(deadline:DispatchTime.now(), repeating: .milliseconds(millisecond))
        timer.setEventHandler {
            DispatchQueue.main.sync {
                action()
            }
        }
        timer.resume()
        SLog.debug("# STimeUtil 启动计时器:%@",key)
    }
    
    dynamic public class func stopTimer(_ key:String)
    {
        if key.isEmpty{
            SLog.debug("# STimeUtil key不能为空")
            return
        }
        guard let timer=timerList[key] else{
            SLog.debug("# STimeUtil 计时器已取消:%@",key)
            return
        }
        timerList.removeValue(forKey: key)
        if timer.isCancelled{
            SLog.debug("# STimeUtil 计时器已取消:%@",key)
        }
        timer.cancel()
        SLog.debug("# STimeUtil 停止计时器:%@",key)
    }
    
    dynamic public class func hasTime(_ key:String)->Bool
    {
        _lock.lock();defer{_lock.unlock()}
        if key.count<1 {
            return false
        }
        return timeList[key] != nil
    }
    
    dynamic public class func start(_ key:String)
    {
        _lock.lock();defer{_lock.unlock()}
        if key.count<1 {
            return
        }
        timeList[key] = Date()
    }
    
    dynamic public class func end(_ key:String) -> Double
    {
        _lock.lock();defer{_lock.unlock()}
        if key.count<1 {
            return 0
        }
        var date:Date?
        for (key,value) in timeList{
            if key.hasPrefix(key){
                date = value
                timeList.removeValue(forKey: key)
                break
            }
        }
        guard let last = date else{
            SLog.debug("找不到计时结束的key:%@",key)
            return 0
        }
        let deltaTime = NSDate().timeIntervalSince(last)
        return deltaTime
    }
    
    // GCD 延迟
    @discardableResult dynamic public class func delay(_ time:TimeInterval,task:@escaping ()->()) -> STask?
    {
        func dispatch_later(block: @escaping ()->()) {
            let t = DispatchTime.now() + time
            DispatchQueue.main.asyncAfter(deadline: t, execute: block)
        }
        var closure: (()->Void)? = task
        var result: STask?
        let delayedClosure: STask = {
            cancel in
            if let internalClosure = closure {
                if (cancel == false) {
                    DispatchQueue.main.async(execute: internalClosure)
                }
            }
            closure = nil
            result = nil
        }
        result = delayedClosure
        dispatch_later {
            if let delayedClosure = result {
                delayedClosure(false)
            }
        }
        return result
    }
    // 取消延迟执行
    dynamic public class func cancel(_ task: STask?)
    {
        task?(true)
    }
}
